package com.toft.widgets.workflow.service.impl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.jbpm.api.Execution;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.HistoryService;
import org.jbpm.api.JbpmException;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.TaskService;
import org.jbpm.api.history.HistoryTask;
import org.jbpm.api.task.Task;
import org.jbpm.pvm.internal.history.model.HistoryActivityInstanceImpl;
import org.jbpm.pvm.internal.history.model.HistoryProcessInstanceImpl;
import org.jbpm.pvm.internal.history.model.HistoryTaskImpl;
import org.jbpm.pvm.internal.model.ActivityImpl;
import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
import org.jbpm.pvm.internal.model.TransitionImpl;
import org.jbpm.pvm.internal.svc.TaskServiceImpl;
import org.jbpm.pvm.internal.task.ParticipationImpl;
import org.jbpm.pvm.internal.task.TaskDefinitionImpl;
import org.jbpm.pvm.internal.task.TaskImpl;

import com.toft.widgets.workflow.adpater.WorkflowQueryAdapter;
import com.toft.widgets.workflow.articulated.IArticulatedProcess;
import com.toft.widgets.workflow.authorization.IAuthorizedManagement;
import com.toft.widgets.workflow.factory.ServiceFactory;
import com.toft.widgets.workflow.factory.impl.ServiceFactoryImpl;
import com.toft.widgets.workflow.model.CompleteTaskResult;
import com.toft.widgets.workflow.model.TaskItem;
import com.toft.widgets.workflow.service.IWorkflowQueryService;
import com.toft.widgets.workflow.service.IWorkflowService;
import com.toft.widgets.workflow.service.JbpmServiceSupport;
import com.toft.widgets.workflow.service.WorkflowFacade;
import com.toft.widgets.workflow.utils.AssistanceUtil;
import com.toft.widgets.workflow.utils.ConstantUtil;
import com.toft.widgets.workflow.utils.ReflectionUtils;
import com.toft.widgets.workflow.utils.TableConstants;

public class WorkflowServiceImpl extends JbpmServiceSupport implements IWorkflowService {

	protected static ServiceFactory serviceFactory = ServiceFactoryImpl.getServiceFactory();

	protected static IWorkflowQueryService workflowQueryService = serviceFactory.getWorkflowQueryService();

	protected static IArticulatedProcess articulatedProcess = serviceFactory.getArticulatedProcess();

	protected static IAuthorizedManagement authorizedManagement = serviceFactory.getAuthorizedManagement();

	/**
	 * 通过流程实例ID启动流程
	 * 
	 * @param processDefinitionId
	 *            流程定义标识
	 * @param variables
	 *            流程变量
	 * @return 流程实例标识
	 */
	public String startProcessInstanceById(String processDefinitionId, Map variables) {

		ProcessInstance processInstance = null;

		if ((null != processDefinitionId) && (!"".equals(processDefinitionId))) {
			processInstance = executionService.startProcessInstanceById(processDefinitionId, variables);
		}
		return processInstance.getId();
	}

	/**
	 * 完成提交节点（即普通任务节点） 如果提交节点是第一次创建，就自动完成， <br>
	 * 否则就不自动完成，需要提交人手动完成任务
	 * 
	 * @param processInstanceId
	 * @param userCode
	 * @return
	 */
	public List completeSubmitActivity(String processInstanceId, String userCode) {

		String taskId = "";

		if (null != processInstanceId && !"".equals(processInstanceId)) {
			TaskImpl task = (TaskImpl) taskService.createTaskQuery().processInstanceId(processInstanceId).uniqueResult();
			if (null != task) {
				taskId = task.getId();
				if (null != task.getSubmitActivity() && task.getSubmitActivity().equals(ConstantUtil.SUBMIT_ACTIVITY)) { // 是提交节点
					if (null != task.getAssignee() && task.getAssignee().equals(userCode)) { // 提交节点参与者为系统当前登录用户
						if (null == taskService.getVariable(task.getId(), ConstantUtil.TASK_COMMNET_TYPE_REFUSE)) { // 提交节点是第一次创建，不是被退回的，就要自动完成
							// 获取流程走向
							String transition = workflowQueryService.getTaskTransition(task.getId(), ConstantUtil.APPROVE_OPERATION_PASS);
							// 完成任务
							taskService.completeTask(task.getId(), transition);
							// 添加审批意见
							taskService.addTaskComment(task.getId(), ConstantUtil.SUBMIT_NAME);
						}
					}
				}
			}
		}
		return workflowQueryService.getNextOperatorsListByProcessInstanceId(processInstanceId);
	}

	/**
	 * 单据提交
	 */
	public CompleteTaskResult startProcessInstanceByMountInfo(String agencyId, String businessType, Map variables, String userCode) {
		CompleteTaskResult result = null;
		logger.info("机构标识：" + agencyId + ",业务类型：" + businessType + ",流程变量：" + variables + ",用户标识：" + userCode);
		try {
			Map map = articulatedProcess.getProcessMountInfo(agencyId, businessType);

			String processDefinitionId = (String) map.get("pdId"); // 流程实例ID
			variables.put(ConstantUtil.BUSINESS_URL, map.get("businessUrl"));// 单据URL
			variables.put(ConstantUtil.BUSINESS_NAME, map.get("businessName"));// 业务类型名称
			variables.put(ConstantUtil.BUSINESS_TYPE, businessType);// 业务类型
			variables.put(ConstantUtil.SUBMIT_USER, userCode);// 提交人
			variables.put(ConstantUtil.AGENCY_ID, agencyId);// 提交用户的机构编号
			String processInstanceId = startProcessInstanceById(processDefinitionId, variables);
			List userList = completeSubmitActivity(processInstanceId, userCode);
			String businessRecordId = (String) variables.get(ConstantUtil.BUSINESS_RECORE_ID);
			boolean isEnded = workflowQueryService.isEndedByProcessInstanceId(processInstanceId);
			if (isEnded) {
				result = new CompleteTaskResult(isEnded, true, processInstanceId, businessType, businessRecordId, null);
			} else {
				result = new CompleteTaskResult(false, true, processInstanceId, businessType, businessRecordId, userList);
			}
		} catch (Exception e) {
			if (e.getCause() != null) {
				throw new JbpmException(e.getCause().getMessage());
			} else {
				throw new JbpmException(e.getMessage());
			}
		}

		return result;
	}

	/**
	 * 单据再次提交
	 */
	public CompleteTaskResult reSubmitProcessInstance(String agencyId, String businessType, Map variables, String userCode) {
		CompleteTaskResult result = null;
		logger.info("机构标识：" + agencyId + ",业务类型：" + businessType + ",流程变量：" + variables + ",用户标识：" + userCode);
		try {
			if (null == variables.get(ConstantUtil.BUSINESS_RECORE_ID)) {
				throw new JbpmException("业务数据ID不存在");
			}
			String businessRecordId = (String) variables.get(ConstantUtil.BUSINESS_RECORE_ID);
			TaskItem taskItem = new TaskItem();
			taskItem.setBusinessType(businessType);
			taskItem.setBusinessRecordId(businessRecordId);
			taskItem.setRefuseToSubmitActivity(true);
			List list = workflowQueryService.findTaskListByProcessInstanceId(taskItem);
			if (list.size() == 0) {
				throw new JbpmException("任务不存在");
			}
			String taskId = ((TaskItem) list.get(0)).getId();
			variables.put(ConstantUtil.TASK_COMMNET_TYPE, ConstantUtil.SUBMIT_OPERATION); // 意见类型
			variables.put(ConstantUtil.AGENCY_ID, agencyId);
			result = completeTask(userCode, taskId, variables, true);
			String processInstanceId = result.getProcessInstanceId();
			List userList = result.getNextOperatorsList();

			boolean isEnded = workflowQueryService.isEndedByProcessInstanceId(processInstanceId);
			if (isEnded) {
				result = new CompleteTaskResult(isEnded, true, processInstanceId, businessType, businessRecordId, null);
			} else {
				result = new CompleteTaskResult(false, true, processInstanceId, businessType, businessRecordId, userList);
			}
		} catch (Exception e) {
			if (e.getCause() != null) {
				throw new JbpmException(e.getCause().getMessage());
			} else {
				throw new JbpmException(e.getMessage());
			}
		}
		return result;
	}

	/**
	 * 
	 */
	public void completeTask(String userCode, Map variable, List taskIds) {
		logger.info(userCode + "," + variable + "," + taskIds.toString());
		long startTime0 = System.currentTimeMillis();
		for (Iterator iter = taskIds.iterator(); iter.hasNext();) {
			String taskId = (String) iter.next();
			CompleteTaskResult result = completeTask(userCode, taskId, variable, false);
			dispatchCompleteTaskResult(result);
		}
		long endTime0 = System.currentTimeMillis();
		logger.info("批量审批耗时：" + (endTime0 - startTime0) + "ms");
	}

	/**
	 * 查询路径,用于当审批完成时,去修改单据状态
	 */
	public Map getJpbm4BusinessInfo(String businessType) {
		Map map = new HashMap();
		String sql = "select id,name,code,operant,query,business_class_name from " + TableConstants.JBPM4_BUSINESS + " where id='" + businessType + "'";
		try {
			map = AssistanceUtil.selectOne(sql, WorkflowFacade.getConnection());
		} catch (SQLException e) {
			throw new JbpmException("查询语句错误," + sql);
		}
		return map;
	}

	/**
	 * 根据审批意见类型进行审批
	 */
	public CompleteTaskResult completeTask(String userCode, String taskId, Map variable, boolean needNextOperators) {
		String commentType = (String) variable.get(ConstantUtil.TASK_COMMNET_TYPE);
		String approveType = ConstantUtil.APPROVE_OPERATION_PASS;
		if (StringUtils.isNotEmpty(commentType) && commentType.equals(ConstantUtil.TASK_COMMNET_TYPE_REFUSE)) {
			approveType = ConstantUtil.APPROVE_OPERATION_REFUSE;
		}
		String transition = workflowQueryService.getTaskTransition(taskId, approveType);
		CompleteTaskResult result = completeTask(userCode, taskId, transition, variable);
		String processInstanceId = result.getProcessInstanceId();
		String businessRecordId = result.getBusinessRecordId();
		String businessType = result.getBusinessType();
		boolean isEnded = result.isEnded();
		List userList = new ArrayList();
		if (needNextOperators && !isEnded) {
			userList = workflowQueryService.getNextOperatorsListByProcessInstanceId(processInstanceId);
		}
		return new CompleteTaskResult(isEnded, result.isBack(), processInstanceId, businessType, businessRecordId, userList);
	}

	/**
	 * 审批完成,修改单据状态
	 * 
	 * @param result
	 */
	private void dispatchCompleteTaskResult(CompleteTaskResult result) {
		String businessRecordId = result.getBusinessRecordId();
		String businessType = result.getBusinessType();
		String businessClassName = "";
		try {
			Map businessInfo = getJpbm4BusinessInfo(businessType);
			businessClassName = (String) businessInfo.get("BUSINESS_CLASS_NAME");
			if (StringUtils.isNotEmpty(businessClassName)) {
				Object obj = Class.forName(businessClassName).newInstance();
				if (result.isEnded()) {
					ReflectionUtils.invokeMethod(obj, "endWorkflow", new Class[] { String.class }, new String[] { businessRecordId });
				} else {
					if (result.isBack()) {
						ReflectionUtils.invokeMethod(obj, "refuseWorkflow", new Class[] { String.class }, new String[] { businessRecordId });
					} else {
						ReflectionUtils.invokeMethod(obj, "approveWorkflow", new Class[] { String.class }, new String[] { businessRecordId });
					}
				}
			}

		} catch (Exception e) {
			if (e instanceof RuntimeException) {
				throw new JbpmException("完成任务时错误," + e.getMessage());
			} else {
				e.printStackTrace();
				throw new JbpmException("完成任务时错误," + e.getMessage());
			}
		}
	}

	/**
	 * 通过流向判断 按键类别 ，前台doDone方法调用
	 */
	public CompleteTaskResult completeTask(String userCode, String taskId, String transition, Map variable, boolean needNextOperators) {
		CompleteTaskResult result = completeTask(userCode, taskId, transition, variable);
		String processInstanceId = result.getProcessInstanceId();
		String businessRecordId = result.getBusinessRecordId();
		String businessType = result.getBusinessType();
		boolean isEnded = result.isEnded();
		List userList = new ArrayList();
		if (needNextOperators && !isEnded) {
			userList = workflowQueryService.getNextOperatorsListByProcessInstanceId(processInstanceId);
		}
		CompleteTaskResult completeTaskResult = new CompleteTaskResult(isEnded, result.isBack(), processInstanceId, businessType, businessRecordId, userList);
		dispatchCompleteTaskResult(completeTaskResult);
		return completeTaskResult;
	}

	/**
	 * 完成任务最终要使用这个方法
	 */
	public CompleteTaskResult completeTask(String userCode, String taskId, String transition, Map variable) {
		logger.info("任务标识：" + taskId + ",任务流向：" + transition + ",流程变量：" + variable + ",用户标识：" + userCode);
		String taskCommentContent = variable.get(ConstantUtil.TASK_COMMENT_CONTENT) == null ? "" : variable.get(ConstantUtil.TASK_COMMENT_CONTENT).toString();
		if (null == taskId || "".equals(taskId)) {
			throw new JbpmException("无效的任务标识！");
		}

		CompleteTaskResult completeTaskResult = null;
		try {
			boolean isBack = false;
			TaskImpl task = (TaskImpl) taskService.getTask(taskId);
			String taskType = task.getTaskType();
			String processInstanceId = task.getExeId();
			String businessRecordId = task.getBusinessRecordId();
			String businessType = task.getBusinessType();
			if (null != task.getSuperTask()) { // 动态任务或者是会签任务
				if (!task.getSuperTask().getState().equals(Task.STATE_OPEN)) {
					throw new JbpmException("动态任务或者会签任务状态错误！");
				}
			}

			if (null == task) { // 要完成的任务已经不存在了
				throw new JbpmException("任务已经不存在！");
			} else if (!task.getState().equals(Task.STATE_OPEN)) { // 要完成的任务不是开启状态
				throw new JbpmException("任务状态错误！");
			}
			// 更新任务变量金额
			String money = null == variable.get(ConstantUtil.BUSINESS_MONEY) ? "" : variable.get(ConstantUtil.BUSINESS_MONEY).toString();
			if (StringUtils.isNotEmpty(money)) {
				variable.put(ConstantUtil.BUSINESS_MONEY, money);
			}

			// 判断该任务是不是子任务，如果是子任务，先完成所有的子任务，再完成父任务
			variable.remove(ConstantUtil.TASK_COMMENT_CONTENT);
			if (ConstantUtil.COUNTERSIGNATURE_TASK.equals(taskType)) {
				isBack = completeCounterSignatureTask(userCode, task, transition, variable);
			} else {
				isBack = completeCommonTask(userCode, task, transition, variable);
			}
			variable.put(ConstantUtil.TASK_COMMENT_CONTENT, taskCommentContent);

			// 添加任务评论
			if (null != variable && !variable.isEmpty()) {
				String taskCommentType = variable.get(ConstantUtil.TASK_COMMNET_TYPE) == null ? "" : variable.get(ConstantUtil.TASK_COMMNET_TYPE).toString();
				taskCommentContent = taskCommentContent.replaceAll("\\" + ConstantUtil.STR_SEPARATOR, "＄");
				taskCommentContent = StringEscapeUtils.escapeHtml(taskCommentContent);
				String message = "".equals(taskCommentContent) ? (taskCommentType + ConstantUtil.STR_SEPARATOR)
						: (taskCommentType + ConstantUtil.STR_SEPARATOR + taskCommentContent);
				taskService.addTaskComment(taskId, message);
			}

			// 流程是否结束
			boolean isEnded = workflowQueryService.isEndedByProcessInstanceId(processInstanceId);

			completeTaskResult = new CompleteTaskResult(isEnded, isBack, processInstanceId, businessType, businessRecordId, null);

		} catch (Exception e) {
			if (e.getCause() != null) {
				throw new JbpmException(e.getCause().getMessage());
			} else {
				e.printStackTrace();
				throw new JbpmException("完成任务时错误:" + e.getMessage());
			}
		} finally {
		}

		return completeTaskResult;
	}

	/**
	 * 普通任务完成方法
	 * 
	 * @param userCode
	 * @param task
	 * @param transition
	 * @param variable
	 * @return
	 */
	private boolean completeCommonTask(String userCode, TaskImpl task, String transition, Map variable) {
		// 设置任务类型：普通任务
		variable.put(ConstantUtil.TASKTYPE, ConstantUtil.TASKTYPE_COMMONTASK);
		boolean isBack = false;
		if (variable.get(ConstantUtil.TASK_COMMNET_TYPE).equals(ConstantUtil.TASK_COMMNET_TYPE_REFUSE)) {
			isBack = true;
		}
		String taskId = task.getId();
		// 直接完成普通任务(无子任务的情况)
		if (null == task.getAssignee()) { // 分配到组上的任务无参与者
			// 将完成任务的用户放入变量中，目的是在组中的用户完成任务时
			// 能为历史任务更新assignee属性值
			variable.put(ConstantUtil.USER_CODE, userCode);
			Set parts = task.getParticipations();
			String groupId = "";
			for (Iterator iter = parts.iterator(); iter.hasNext();) {
				ParticipationImpl p = (ParticipationImpl) iter.next();
				if (null != p) {
					groupId = p.getGroupId();
				}
			}

			if (!"".equals(groupId)) {
				Map conditions = new HashMap();
				conditions.put(ConstantUtil.AGENCY_ID, task.getAgencyId());
				conditions.put(ConstantUtil.DEPARTMENT_ID, task.getDepartmentId());
				conditions.put("groupId", groupId);
				conditions.put("conn", WorkflowFacade.getConnection());

				boolean flage = false;
				List userCodes = ReflectionUtils.convertElementPropertyToList(WorkflowQueryAdapter.getInstance().getUserListByGroupId(conditions), "CODE");
				for (Iterator it = userCodes.iterator(); it.hasNext();) {
					String uc = (String) it.next();
					if (userCode.equals(uc)) { // 组里用户不存在授权
						flage = true;
						break;
					}
				}
				if (flage) { // 组里用户不存在授权
					variable.put("taskAgent", "");
				} else { // 组里用户存在授权
					variable.put("taskAgent", userCode);
				}
			}
		} else if (userCode.equals(task.getAssignee())) { // 任务本身参与者完成任务(无代理人)
			variable.put("taskAgent", ""); // 清除代理人标识(当上一个任务为代理人完成时)
			variable.put(ConstantUtil.USER_CODE, userCode);
		} else if (!userCode.equals(task.getAssignee())) { // 任务代理人完成任务
			// 设置代理人完成任务的标志
			variable.put(ConstantUtil.USER_CODE, userCode);
			variable.put("taskAgent", userCode);
		}
		taskService.completeTask(taskId, transition, variable);
		return isBack;
	}

	/**
	 * 会签任务完成方法
	 * 
	 * @param userCode
	 * @param task
	 * @param transition
	 * @param variable
	 * @return
	 */
	private boolean completeCounterSignatureTask(String userCode, TaskImpl task, String transition, Map variable) {
		// 设置任务类型：会签任务
		variable.put(ConstantUtil.TASKTYPE, ConstantUtil.TASKTYPE_SIGNATURETASK);
		Session session = WorkflowFacade.getSession();
		TaskImpl parentTask = task.getSuperTask(); // 父任务
		Set subTasks = parentTask.getSubTasks(); // 子任务
		// 会签通过数
		int passVotes = 0;
		int allVotes = subTasks.size();
		boolean isBack = false;
		Map variableMap = new HashMap();
		// 根据任务定义获取会签的参数
		TaskDefinitionImpl taskDefinition = parentTask.getTaskDefinition();
		String countersignType = taskDefinition.getCountersignType();
		String countersignValueString = taskDefinition.getCountersignValue();
		int countersignValue = 0;
		if (StringUtils.isNotEmpty(countersignValueString)) {
			countersignValue = Integer.parseInt(countersignValueString);
		}

		for (Iterator iter = subTasks.iterator(); iter.hasNext();) {
			TaskImpl subTask = (TaskImpl) iter.next();
			if (subTask.getId().equals(task.getId())) {
				HistoryTaskImpl historyTask = new HistoryTaskImpl(task);
				historyTask.setEndTime(new Date());
				historyTask.setExecutionId(task.getSuperTask().getExecutionId());
				historyTask.setOutcome(transition);
				historyTask.setState(Task.STATE_COMPLETED);
				long duration = (new Date().getTime()) - (task.getCreateTime().getTime());
				historyTask.setDuration(duration);

				historyTask.setBusinessType(task.getBusinessType());
				historyTask.setBusinessName(task.getBusinessName());
				historyTask.setBusinessSN(task.getBusinessSN());
				historyTask.setBusinessRecordId(task.getBusinessRecordId());
				historyTask.setBusinessMoney(task.getBusinessMoney());
				historyTask.setAgencyId(task.getAgencyId()); // 模块标识
				historyTask.setDepartmentId(task.getDepartmentId()); // 客户标识
				historyTask.setUrl(task.getUrl());
				historyTask.setName(task.getActivityName()); // 设置历史任务的名称
				historyTask.setParentId(parentTask.getId()); // 设置历史任务的父任务标识
				HistoryProcessInstanceImpl historyProcessInstance = new HistoryProcessInstanceImpl(task.getExecution());
				historyTask.setHistoryProcessInstance(historyProcessInstance);
				historyTask.setExeId(task.getExeId()); // add by qlzou
				historyTask.setApplicationUser(task.getApplicationUser());
				// at 2010-5-27
				if (userCode.equals(subTask.getAssignee())) { // 任务参与者完成任务
					variable.put(ConstantUtil.USER_CODE, "");
					historyTask.setAgentId(null);
				} else if (!userCode.equals(subTask.getAssignee())) { // 任务代理人完成任务
					// 设置代理人完成任务的标志
					variable.put(ConstantUtil.USER_CODE, userCode);
					historyTask.setAssignee(userCode);
					historyTask.setAgentId(userCode);
				}

				taskService.completeTask(subTask.getId(), variable);
				session.save(historyTask);
				// 将审批结果记入任务变量
				Set variableNames = new HashSet();
				variableNames.add(ConstantUtil.COUNTERSIGN_ALL_NUM);
				variableNames.add(ConstantUtil.COUNTERSIGN_PASS_NUM);
				variableMap = taskService.getVariables(parentTask.getId(), variableNames);
				String allVotesStr = (String) variableMap.get(ConstantUtil.COUNTERSIGN_ALL_NUM);
				String passVotesStr = (String) variableMap.get(ConstantUtil.COUNTERSIGN_PASS_NUM);
				if (StringUtils.isNotEmpty(allVotesStr) && StringUtils.isNotEmpty(passVotesStr)) {
					allVotes = Integer.parseInt(allVotesStr);
					passVotes = Integer.parseInt(passVotesStr);
				}
				Map strategyVariable = new HashMap();
				if (variable.get(ConstantUtil.TASK_COMMNET_TYPE).equals(ConstantUtil.TASK_COMMNET_TYPE_ACCEPT)) {
					passVotes++;
				}
				strategyVariable.put(ConstantUtil.COUNTERSIGN_ALL_NUM, String.valueOf(allVotes));
				strategyVariable.put(ConstantUtil.COUNTERSIGN_PASS_NUM, String.valueOf(passVotes));
				taskService.setVariables(parentTask.getId(), strategyVariable);
			}

		}
		if (subTasks.size() == 1) {
			// 父任务中无参与者和代理人，所以要清空变量中的参与者和代理人
			variable.put(ConstantUtil.USER_CODE, "");
			variable.put("taskAgent", "");
			String approveType = "";
			if (isPassThroungh(allVotes, passVotes, countersignType, countersignValue)) {
				approveType = ConstantUtil.APPROVE_OPERATION_PASS;
				variable.put(ConstantUtil.COUNTERSIGN_RESULT, "true");
			} else {
				isBack = true;
				approveType = ConstantUtil.APPROVE_OPERATION_REFUSE;
				variable.put(ConstantUtil.COUNTERSIGN_RESULT, "false");
			}
			// 清空会签结果
			Map strategyVariable = new HashMap();
			strategyVariable.put(ConstantUtil.COUNTERSIGN_ALL_NUM, null);
			strategyVariable.put(ConstantUtil.COUNTERSIGN_PASS_NUM, null);
			strategyVariable.put(ConstantUtil.COUNTERSIGN_RESULT, null);
			taskService.setVariables(parentTask.getId(), strategyVariable);
			// 根据会签结果找流向
			transition = workflowQueryService.getTaskTransition(parentTask.getId(), approveType);
			taskService.completeTask(parentTask.getId(), transition, variable);
		}
		return isBack;
	}

	/**
	 * 会签任务完成条件判断:分按个数,按百分比,以及全部完成三种情况
	 * 
	 * @param allVotes
	 *            参考会签任务的总人数
	 * @param passVotes
	 *            审批同意的人数
	 * @param countersignType
	 *            完成会签任务种类
	 * @param countersignValue
	 *            完成会签任务数目
	 * @return
	 */
	private boolean isPassThroungh(int allVotes, int passVotes, String countersignType, int countersignValue) {
		if (countersignType.equals("number")) {
			if (countersignValue > allVotes)
				countersignValue = allVotes;
			return passVotes >= countersignValue;
		} else if (countersignType.equals("percent")) {
			return (passVotes * 1.00 / allVotes * 1.00) * 100 >= countersignValue;
		} else {
			return passVotes == allVotes;
		}
	}

	/**
	 * 按taskId结束流程实例
	 * 
	 * @param taskId
	 *            任务标识
	 */
	public void endProcessInstance(String taskId) {
		logger.info("任务标识：" + taskId);
		TaskImpl task = (TaskImpl) taskService.getTask(taskId);
		if (null == task) { // 要完成的任务已经不存在了
			throw new JbpmException("任务已经不存在！");
		} else if (!task.getState().equals(Task.STATE_OPEN)) { // 要完成的任务不是开启状态
			throw new JbpmException("任务状态错误！");
		}
		executionService.endProcessInstance(task.getExeId(), Execution.STATE_ENDED);
	}

	public String endProcessInstance(String processInstanceId, String taskId) {
		executionService.endProcessInstance(processInstanceId, Execution.STATE_ENDED);
		return "ended";
	}

	/**
	 * 按流程实例ID和业务类型结束流程实例
	 */
	public String endProcessInstanceforChangeStatus(String processInstanceId, String businessType) {
		String message = endProcessInstance(processInstanceId, "");
		String businessClassName = "";
		try {
			Map businessInfo = getJpbm4BusinessInfo(businessType);
			businessClassName = (String) businessInfo.get("BUSINESS_CLASS_NAME");
			if (StringUtils.isNotEmpty(businessClassName)) {
				Object obj = Class.forName(businessClassName).newInstance();
				ReflectionUtils.invokeMethod(obj, "stopWorkflow", new Class[] { String.class }, new String[] { processInstanceId });
			}
		} catch (Exception e) {
			throw new JbpmException(e.getMessage());
		}
		return message;
	}

	/**
	 * 拾取组任务
	 */
	public String takeTaskFromGroup(String taskId, String userCode, String groupId) {

		if (null == taskId || "".equals(taskId) || "".equals(userCode)) {
			throw new JbpmException("无效的任务标识用户标识!");
		}

		String assignee = "";
		TaskServiceImpl taskServiceImpl = (TaskServiceImpl) taskService;
		Task t = taskServiceImpl.getTask(taskId);
		if (t != null && null != t.getAssignee() && !"".equals(t.getAssignee())) { // 任务已经被用户拾取
			assignee = t.getAssignee();
		} else { // 任务没有被用户拾取
			taskServiceImpl.takeTask(taskId, userCode);
			Session session = WorkflowFacade.getSession();
			try {
				TaskImpl task = (TaskImpl) session.get(TaskImpl.class, new Long(taskId));
				Set participations = task.getParticipations();
				for (Iterator iter = participations.iterator(); iter.hasNext();) {
					ParticipationImpl p = (ParticipationImpl) iter.next();
					if (p.getTask().getId().equals(taskId)) {
						p.setState("0");
					}
				}

				// 拾取组任务时，设置任务代理人
				String businessType = task.getBusinessType();
				Map conditions = new HashMap();
				conditions.put("author", userCode);
				conditions.put("businessType", businessType);
				conditions.put(ConstantUtil.AGENCY_ID, "");
				conditions.put(ConstantUtil.DEPARTMENT_ID, "");
				conditions.put("conn", WorkflowFacade.getConnection());
				String auths = authorizedManagement.getAuths(conditions);
				if (!"".equals(auths)) {
					task.setAgentId(auths);
				}
			} catch (Exception e) {
				throw new JbpmException("拾取组任务时异常!" + e);
			} finally {
			}
		}

		return assignee;

	}

	/**
	 * 将个人任务列表中的组任务还回到组任务列表中
	 */
	public void revertTaskToGroup(String taskId, String userCode, String groupId) {

		if (null == taskId && "".equals(taskId) && "".equals(userCode)) {
			throw new JbpmException("无效的任务标识用户标识!");
		}

		TaskServiceImpl taskServiceImpl = (TaskServiceImpl) taskService;
		Session session = WorkflowFacade.getSession();
		TaskImpl task = null;
		try {
			task = (TaskImpl) session.get(TaskImpl.class, new Long(taskId));

			Set participations = task.getParticipations();
			if (null != participations && (participations.size() > 0)) {
				for (Iterator iter = participations.iterator(); iter.hasNext();) {
					ParticipationImpl p = (ParticipationImpl) iter.next();
					if (p.getTask().getId().equals(task.getId())) {
						if (p.getState().equals("0")) {
							p.setState("1");
						}
					}
				}
				if (null != task.getAgentId()) {
					task.setAgentId(null);
				}

			}
			// 是组任务才将任务还回到组中，否则不作任何操作
			if (null != participations && (participations.size() > 0)) {
				taskServiceImpl.assignTask(taskId, null);
			}
		} catch (Exception e) {
			throw new JbpmException("归还组任务时异常!" + e);
		} finally {
		}

	}

	/**
	 * 判断流程实例是否存在
	 */
	public boolean isExistProcessInstance(String processDefinitionId) {

		if (null == processDefinitionId || "".equals(processDefinitionId)) {
			throw new JbpmException("无效的流程定义标识！");
		}

		List pis = executionService.createProcessInstanceQuery().processDefinitionId(processDefinitionId).list();

		if ((null != pis) && (!pis.isEmpty()) && (pis.size() > 0)) {
			return true;
		}

		return false;

	}

	/**
	 * 收回任务代理人，授权记录停用后调用该方法来更新任务的代理人， 主要是将任务的代理人删除
	 */
	public void recoveryTaskAgent(String businessType, String userCode, String agentId) {

		if ("".equals(businessType) || "".equals(userCode) || "".equals(agentId)) {
			throw new JbpmException("更新任务代理人时有误 " + businessType + "-" + userCode + "-" + agentId);
		}

		String executionId = "";
		String taskAssignee = "";
		String taskAgents = "";

		TaskServiceImpl taskServiceImpl = (TaskServiceImpl) taskService;
		List tasks = taskServiceImpl.createTaskQuery().list();

		Session session = WorkflowFacade.getSession();
		try {

			for (Iterator iter = tasks.iterator(); iter.hasNext();) {
				TaskImpl task = (TaskImpl) iter.next();
				if (null != task.getAssignee() && null != task.getBusinessType() && null != task.getAgentId()) {

					if ((task.getAssignee().equals(userCode)) && (task.getBusinessType().equals(businessType))) { // 授权记录的授权人是任务参与者

						TaskImpl t = (TaskImpl) session.get(TaskImpl.class, new Long(task.getId()));
						if (null != t.getAgentId() && !"".equals(t.getAgentId())) {
							t.setAgentId(null); // 授权记录的授权人为任务参与者时，无论任务的代理人有多少，都置为空
						}

						// 用于更新上一历史任务的下一级处理人使用
						taskAssignee = t.getAssignee();
						if (null != t.getAgentId() && !"".equals(t.getAgentId())) {
							taskAgents = t.getAgentId();
						}
						executionId = t.getExecutionId();

					} else if (null != task.getAgentId() && !"".equals(task.getAgentId())) { // 授权记录的授权人是任务的代理人(代理人之一)

						TaskImpl t = (TaskImpl) session.get(TaskImpl.class, new Long(task.getId()));
						if (t.getAgentId().indexOf(",") != -1) { // 任务拥有多个代理人
							if (t.getAgentId().indexOf(userCode) != -1 && t.getBusinessType().equals(businessType)) {
								String finalAgent = "";
								String[] tempAgents = t.getAgentId().split("\\,");
								for (int i = 0; i < tempAgents.length; i++) {
									if (!tempAgents[i].equals(agentId)) {
										finalAgent += tempAgents[i] + ",";
									}
								}
								if (!"".equals(finalAgent) && (finalAgent.indexOf(",") != -1)) {
									finalAgent = finalAgent.substring(0, finalAgent.lastIndexOf(","));
								}
								if (!"".equals(finalAgent)) {
									t.setAgentId(finalAgent);
								}
							}
						}

						// 用于更新上一历史任务的下一级处理人使用
						taskAssignee = t.getAssignee();
						if (null != t.getAgentId() && !"".equals(t.getAgentId())) {
							taskAgents = t.getAgentId();
						}
						executionId = t.getExecutionId();
					}
				}

			}

			// 即时更新历史任务的下一级处理人，主要是将待办任务中的代理人从历史任务的下一处理人中删除
			if (null != executionId && !"".equals(executionId)) {
				HistoryTaskImpl hTask = null;

				String queryString = "select ht from " + HistoryTaskImpl.class.getName()
						+ " as ht where ht.executionId = :executionId and ht.state = :state order by ht.dbid desc";
				Query query = session.createQuery(queryString);
				query.setParameter("executionId", executionId);
				query.setParameter("state", HistoryTask.STATE_COMPLETED);
				List hTasks = query.list();
				if (null != hTasks && !hTasks.isEmpty()) {
					hTask = (HistoryTaskImpl) hTasks.get(0);
				}

				if (null != hTask) {
					HistoryTaskImpl historyTask = (HistoryTaskImpl) session.get(HistoryTaskImpl.class, new Long(hTask.getId()));
					if (null != historyTask && historyTask.getState().equals(HistoryTask.STATE_COMPLETED)) {

						String nextOperators = "";
						if (!"".equals(taskAssignee)) {
							nextOperators += (taskAssignee + "," + taskAgents);
						}

						String finalNextOperators = "";
						if (!"".equals(nextOperators)) {
							if ((nextOperators.indexOf(",") != -1)) {
								String[] tempNextOperators = nextOperators.split("\\,");
								Map conditions = new HashMap();
								conditions.put(ConstantUtil.AGENCY_ID, historyTask.getAgencyId());
								conditions.put(ConstantUtil.DEPARTMENT_ID, historyTask.getDepartmentId());
								conditions.put("conn", WorkflowFacade.getConnection());
								for (int i = 0; i < tempNextOperators.length; i++) {
									conditions.put("code", tempNextOperators[i]);
									finalNextOperators += (WorkflowQueryAdapter.getInstance().getUserNameByCode(conditions) + ",");
								}
							} else {
								Map conditions = new HashMap();
								conditions.put(ConstantUtil.AGENCY_ID, historyTask.getAgencyId());
								conditions.put(ConstantUtil.DEPARTMENT_ID, historyTask.getDepartmentId());
								conditions.put("conn", WorkflowFacade.getConnection());
								conditions.put("code", nextOperators);
								finalNextOperators += (WorkflowQueryAdapter.getInstance().getUserNameByCode(conditions) + ",");
							}
						}

						if (!"".equals(finalNextOperators)) {
							if ((finalNextOperators.indexOf(",") != -1)) {
								finalNextOperators = finalNextOperators.substring(0, finalNextOperators.lastIndexOf(","));
							}
							historyTask.setNextOperator(finalNextOperators);
						}

					}

				}
			}

		} catch (Exception e) {
			throw new JbpmException("业务授权时更新任务代理人异常!" + e);
		} finally {
		}

	}

	/**
	 * 更新任务代理人，在启用授权时会调用该方法来更新任务参与者， 主要是为任务添加代理人
	 */
	public void updateTaskAssignee(String businessType, String userCode, String agentId) {

		if ("".equals(businessType) || "".equals(userCode) || "".equals(agentId)) {
			throw new JbpmException("更新任务代理人时有误 " + businessType + "-" + userCode + "-" + agentId);
		}

		String executionId = "";
		String taskAssignee = "";
		String taskAgentId = "";
		Session session = WorkflowFacade.getSession();

		TaskServiceImpl taskServiceImpl = (TaskServiceImpl) taskService;
		List tasks = taskServiceImpl.createTaskQuery().list();

		try {
			for (Iterator iter = tasks.iterator(); iter.hasNext();) {
				TaskImpl task = (TaskImpl) iter.next();
				if (null != task.getAssignee() && null != task.getBusinessType()
						&& (task.getAssignee().equals(userCode) && (task.getBusinessType().equals(businessType)))) { // 授权记录的授权人是任务的参与者

					TaskImpl t = (TaskImpl) session.get(TaskImpl.class, new Long(task.getId()));
					String taskAgents = "";
					if (null != t.getAgentId() && !"".equals(t.getAgentId())) { // 任务已经拥有代理人
						if (t.getAgentId().indexOf(",") != -1) { // 任务拥有多个代理人
							taskAgents = t.getAgentId() + "," + agentId;
						} else { // 任务拥有一个代理人
							taskAgents = t.getAgentId() + "," + agentId;
						}

					} else { // 任务没有代理人
						taskAgents = agentId;
					}

					if (!"".equals(taskAgents)) {
						t.setAgentId(taskAgents);
					}

					if (null != t) {
						// 用于更新上一历史任务的下一级处理人使用
						executionId = t.getExecutionId();
						taskAssignee = t.getAssignee();
						if (null != t.getAgentId() && !"".equals(t.getAgentId())) {
							taskAgentId = t.getAgentId();
						}
					}

				} else if (null != task.getAgentId() && !"".equals(task.getAgentId()) && (task.getAgentId().indexOf(userCode) != -1)
						&& task.getBusinessType().equals(businessType)) { // 授权记录的的授权人是任务的代理者(代理者之一)
					TaskImpl t = (TaskImpl) session.get(TaskImpl.class, new Long(task.getId()));
					String taskAgents = "";
					taskAgents = t.getAgentId() + "," + agentId;
					if (!"".equals(taskAgents)) {
						t.setAgentId(taskAgents);
					}
					if (null != t) {
						// 用于更新上一历史任务的下一级处理人使用
						executionId = t.getExecutionId();
						taskAssignee = t.getAssignee();
						if (null != t.getAgentId() && !"".equals(t.getAgentId())) {
							taskAgentId = t.getAgentId();
						}
					}
				}

			}

			// 更新授权记录时为历史任务的下一级处理人添加下一任务的代理人，
			// 主要是将任务的代理人添加到历史任务的下一处理人中
			if (null != executionId && !"".equals(executionId)) {
				HistoryTaskImpl hTask = null;

				String queryString = "select ht from " + HistoryTaskImpl.class.getName()
						+ " as ht where ht.executionId = :executionId and ht.state = :state order by ht.dbid desc";
				Query query = session.createQuery(queryString);
				query.setParameter("executionId", executionId);
				query.setParameter("state", HistoryTask.STATE_COMPLETED);
				List hTasks = query.list();
				if (null != hTasks && !hTasks.isEmpty()) {
					hTask = (HistoryTaskImpl) hTasks.get(0);
				}

				if (null != hTask) {
					HistoryTaskImpl historyTask = (HistoryTaskImpl) session.get(HistoryTaskImpl.class, new Long(hTask.getId()));
					if (null != historyTask && historyTask.getState().equals(HistoryTask.STATE_COMPLETED)) {
						String nextOperators = "";
						String finalNextOperator = "";
						if (!"".equals(taskAssignee)) {
							nextOperators = taskAssignee + "," + taskAgentId;
						}

						if (!"".equals(nextOperators) && (nextOperators.indexOf(",") != -1)) {
							String[] tempNextOperators = nextOperators.split("\\,");
							Map conditions = new HashMap();
							conditions.put(ConstantUtil.AGENCY_ID, historyTask.getAgencyId());
							conditions.put(ConstantUtil.DEPARTMENT_ID, historyTask.getDepartmentId());
							conditions.put("conn", WorkflowFacade.getConnection());
							for (int i = 0; i < tempNextOperators.length; i++) {
								conditions.put("code", tempNextOperators[i]);
								finalNextOperator += (WorkflowQueryAdapter.getInstance().getUserNameByCode(conditions) + ",");
							}
						}

						if (!"".equals(finalNextOperator) && (finalNextOperator.indexOf(",") != -1)) {
							finalNextOperator = finalNextOperator.substring(0, finalNextOperator.lastIndexOf(","));
							historyTask.setNextOperator(finalNextOperator);
						}

					}
				}
			}

		} catch (Exception e) {
			throw new JbpmException("业务授权时更新任务代理人异常!" + e);
		} finally {
		}

	}

	/**
	 * 流程监控挂起任务
	 */
	public String suspendProcessInstance(String processInstanceId) {

		if (null == processInstanceId || "".equals(processInstanceId)) {
			throw new JbpmException("不能挂起无效的流程实例！");
		}

		ProcessInstance pi = workflowQueryService.findProcessInstanceById(processInstanceId);
		ExecutionImpl execution = (ExecutionImpl) pi;
		Session session = WorkflowFacade.getSession();

		String queryString = "select task from " + TaskImpl.class.getName() + " as task where task.executionId like :processInstanceId";
		try {

			execution = (ExecutionImpl) session.get(ExecutionImpl.class, new Long(execution.getDbid()));

			if (!execution.isSuspended()) {
				execution.setState(Execution.STATE_SUSPENDED);
				Query query = session.createQuery(queryString).setString("processInstanceId", processInstanceId + "%");
				List tasks = query.list();
				for (Iterator iter = tasks.iterator(); iter.hasNext();) {
					TaskImpl task = (TaskImpl) iter.next();
					task.setState(Task.STATE_SUSPENDED);
					if (!task.getSubTasks().isEmpty()) { // 拥有子任务
						Set subTasks = task.getSubTasks();
						for (Iterator iterator = subTasks.iterator(); iterator.hasNext();) {
							TaskImpl subTask = (TaskImpl) iterator.next();
							subTask.setState(Task.STATE_SUSPENDED);
						}
					}
				}
			}

		} catch (Exception e) {
			// e.printStackTrace();
			throw new JbpmException("挂起流程实例时异常!" + e);
		} finally {
		}

		return execution.getState();
	}

	/**
	 * 流程监控唤醒任务
	 */
	public String resumeProcessInstance(String processInstanceId) {

		if (null == processInstanceId || "".equals(processInstanceId)) {
			throw new JbpmException("不能唤醒无效的流程实例！");
		}

		ProcessInstance pi = workflowQueryService.findProcessInstanceById(processInstanceId);

		ExecutionImpl execution = (ExecutionImpl) pi;
		Session session = WorkflowFacade.getSession();
		String queryString = "select task from " + TaskImpl.class.getName() + " as task where task.executionId like :processInstanceId";

		try {

			execution = (ExecutionImpl) session.get(ExecutionImpl.class, new Long(execution.getDbid()));

			if (execution.isSuspended()) {
				execution.setState(Execution.STATE_ACTIVE_ROOT);
				Query query = session.createQuery(queryString).setString("processInstanceId", processInstanceId + "%");
				List tasks = query.list();
				for (Iterator iter = tasks.iterator(); iter.hasNext();) {
					TaskImpl task = (TaskImpl) iter.next();
					if (Task.STATE_SUSPENDED.equals(task.getState())) {
						task.setState(Task.STATE_OPEN);
					}
					if (!task.getSubTasks().isEmpty()) { // 拥有子任务
						Set subTasks = task.getSubTasks();
						for (Iterator iterator = subTasks.iterator(); iterator.hasNext();) {
							TaskImpl subTask = (TaskImpl) iterator.next();
							if (Task.STATE_SUSPENDED.equals(subTask.getState())) {
								subTask.setState(Task.STATE_OPEN);
							}
						}
					}
				}
			}

		} catch (Exception e) {
			throw new JbpmException("唤醒流程实例时异常!" + e);
		} finally {
		}

		return execution.getState();
	}

	/**
	 * 动态创建连接当前任务节点至名称为destName的节点的Transition
	 * 
	 * @param taskId
	 *            任务节点ID
	 * @param sourceName
	 *            源节点名称
	 * @param destName
	 *            目标节点名称
	 */
	public String addOutTransition(String taskId, String destName) {

		try {
			TaskImpl task = (TaskImpl) taskService.getTask(taskId);
			ProcessDefinitionImpl pd = (ProcessDefinitionImpl) task.getProcessInstance().getProcessDefinition();
			List list = pd.getActivities();
			for (Iterator iter = list.iterator(); iter.hasNext();) {
				ActivityImpl activity = (ActivityImpl) iter.next();
				System.out.println(activity.getName());
			}
			// 取得当前流程的活动定义
			ActivityImpl sourceActivity = pd.findActivity(task.getName());
			// 取得目标的活动定义
			ActivityImpl destActivity = pd.findActivity(destName);
			// 为两个节点创建连接
			TransitionImpl transition = sourceActivity.createOutgoingTransition();
			transition.setName("to" + destName);
			transition.setDestination(destActivity);
			sourceActivity.addOutgoingTransition(transition);
			return transition.getName();
		} catch (Exception ex) {
			ex.printStackTrace();

		} finally {

		}
		return null;
	}

	/**
	 * 回滚任务
	 * 
	 * @param processInstanceId
	 *            流程实例ID
	 * @param toActivityName
	 *            目标任务名称
	 * @return "ok"成功 否则 错误信息
	 */

	public CompleteTaskResult rollbackTask(String processInstanceId, String destActivityName) {
		CompleteTaskResult result = null;
		// 获取执行，任务，历史三种服务
		ExecutionService executionService = JbpmServiceSupport.executionService;
		TaskService taskService = JbpmServiceSupport.taskService;
		HistoryService historyService = JbpmServiceSupport.historyService;

		// EnvironmentImpl environment = environmentFactory.openEnvironment();
		try {
			Session session = WorkflowFacade.getSession();
			ExecutionImpl exec = (ExecutionImpl) executionService.findExecutionById(processInstanceId);
			ActivityImpl currentActivity = exec.getActivity();// 获取当前活动节点
			TransitionImpl transition = currentActivity.createOutgoingTransition();// 新建一个回滚transition
			List incomingTransitions = currentActivity.getIncomingTransitions();// 获取进入当前节点的transitions
			transition.setName("_transition_for_rollback_");
			for (Iterator iterator = incomingTransitions.iterator(); iterator.hasNext();) {
				TransitionImpl incomingTransition = (TransitionImpl) iterator.next();
				if (incomingTransition.getSource().getName().equals(destActivityName)) {
					transition.setDestination(incomingTransition.getSource());
				}
			}
			Task currentTask = (Task) taskService.createTaskQuery().processInstanceId(processInstanceId).list().get(0);// jbpm_task表中的任务
			Map rollbackVariables = new HashMap();
			rollbackVariables.put(ConstantUtil.TASK_COMMNET_TYPE, ConstantUtil.TASK_COMMNET_TYPE_REFUSE);
			result = this.completeTask("[system]", currentTask.getId(), "_transition_for_rollback_", rollbackVariables, false);

			// 清除当前活动的历史记录，删除历史活动室里以及历史记录
			List list = historyService.createHistoryActivityInstanceQuery().activityName(destActivityName).executionId(processInstanceId).list();
			for (Iterator iterator = list.iterator(); iterator.hasNext();) {
				HistoryActivityInstanceImpl hActInst = (HistoryActivityInstanceImpl) iterator.next();
				// 使用Hibernate session对象直接操作持久层
				session.delete(hActInst);
			}
			list = historyService.createHistoryActivityInstanceQuery().executionId(processInstanceId).activityName(currentTask.getName()).list();
			for (Iterator iterator = list.iterator(); iterator.hasNext();) {
				HistoryActivityInstanceImpl hActInst = (HistoryActivityInstanceImpl) iterator.next();
				// 使用Hibernate session对象直接操作持久层
				session.delete(hActInst);
			}
			session.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// environment.close();
		}
		return result;
	}
}
